﻿using System;
using System.Configuration;
using System.Collections.Generic;
using System.Text;
using System.IO;

using AKMII.DMRA.Common;
using AKMII.DMRA.DataAccess;

using log4net;

namespace AKMII.DMRA.DataLoader
{
    public class Formatter
    {
        private string rawFileName;

        public void Process(string source)
        {
            if (!string.IsNullOrEmpty(source))
            {
                DirectoryInfo di = new DirectoryInfo(source);
                FileInfo[] fi = di.GetFiles("*.txt");
                bool isNeedFormat = false;

                if (fi != null && fi.Length > 0)
                {
                    try
                    {
                        CommandHistoryAccessor accessor = new CommandHistoryAccessor();
                        DateTime dateTime = accessor.GetLastExecuteTime(Command.Format.ToString());

                        foreach (FileInfo file in fi)
                        {
                            if (file.LastWriteTime > dateTime)
                            {
                                isNeedFormat = true;
                            }
                        }

                        if (isNeedFormat)
                        {
                            LeadAccessor leadAccessor = new LeadAccessor();
                            leadAccessor.DeleteLead();

                            foreach (FileInfo file in fi)
                            {
                                if (file.LastWriteTime > dateTime)
                                {
                                    DateTime lastExecuteTime = DateTime.Now;

                                    if (Format(Path.Combine(source, file.Name)))
                                    {
                                        accessor.UpdateLastExecuteTime(Command.Format.ToString(), lastExecuteTime);
                                    }
                                }
                            }

                            UserAccessor userAccessor = new UserAccessor();
                            List<MarketDirector> marketDirectors = userAccessor.GetDivisionAdmins();

                            ZipAccessor zipAccessor = new ZipAccessor();
                            zipAccessor.InsertLeadBlock();

                            if (marketDirectors != null)
                            {
                                foreach (var marketDirector in marketDirectors)
                                {
                                    Mail mail = new Mail();
                                    mail.Subject = Constants.SubjectForAssignLeads;
                                    mail.Content = Constants.ContentForAssignLeads;
                                    string[] divMails = marketDirector.Email.Split(';');
                                    foreach (string curMail in divMails)
                                    {
                                        mail.Recipients = new List<string>() { curMail };
                                        Utility.Send(mail);
                                        System.Threading.Thread.Sleep(30000);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Exception occurs in format process", ex);
                    }
                }
            }
        }

        private bool Format(string file)
        {
            this.rawFileName = file;

            try
            {
                if (!File.Exists(this.rawFileName))
                {
                    string msg = string.Format("Non-existing file {0}.", this.rawFileName);
                    Logger.Info(msg);
                }
                else
                {
                    Logger.Info("Begin parse " + this.rawFileName);

                    ParseFile();

                    Logger.Info("Finish parse " + this.rawFileName);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Exception occurs in format files", ex);
                return false;
            }

            return true;
        }

        private void ParseFile()
        {
            StreamReader reader = null;
            try
            {
                reader = new StreamReader(this.rawFileName);

                if (reader != null)
                {
                    List<Lead> leads = new List<Lead>();
                    LeadAccessor leadAccessor = new LeadAccessor();
                    int count = 0;

                    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
                    {
                        Lead lead = null;

                        if (this.rawFileName.IndexOf("Base", StringComparison.CurrentCultureIgnoreCase) > -1)
                        {
                            lead = ConstructLeadForAL(line);
                        }
                        else if (this.rawFileName.IndexOf("Prosp", StringComparison.CurrentCultureIgnoreCase) > -1)
                        {
                            lead = ConstructLeadForNB(line);
                        }
                        else
                        {
                            lead = ConstructLead(line);
                        }
                        
                        leads.Add(lead);

                        if (leads.Count == 10000)
                        {
                            leadAccessor.AddLead(leads);
                            leads.Clear();

                            Logger.Info("Add 10000 records");
                        }

                        count++;
                    }

                    leadAccessor.AddLead(leads);
                    Logger.Info("Add " + leads.Count.ToString() + " records");
                    Logger.Info("This file constains " + count.ToString() + " records");
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Exception occurs in parse file", ex);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                    reader = null;
                }
            }
        }

        private Lead ConstructLeadForAL(string line)
        {
            Lead lead = new Lead();

            lead.SelPersonId = line.Substring(0, 9).Trim();
            lead.MdNumber = line.Substring(2723, 4).Trim();
            lead.SequenceNumber = line.Substring(2727, 9).Trim();
            lead.County = line.Substring(2736, 27).Trim();
            lead.PreferCity = line.Substring(2763, 27).Trim();
            lead.CallType = line.Substring(2790, 1).Trim();
            lead.LeadType = line.Substring(2791, 1).Trim();
            lead.Latitude = line.Substring(2792, 9).Trim();
            lead.Longitude = line.Substring(2801, 9).Trim();
            lead.LeadBlockCode = line.Substring(2810, 9).Trim();
            lead.Zip = line.Substring(2810, 9).Substring(0, 5).Trim();
            lead.Division = line.Substring(2823, 2).Trim();
            lead.Market = line.Substring(2825, 2).Trim();
            //lead.Territory = line.Substring(2827, 2).Trim();
            
            lead.PersonStatus = line.Substring(2833, 1).Trim();
            lead.PcLeadType = line.Substring(3009, 1).Trim();
            lead.City = line.Substring(3070, 27).Trim();

            if (lead.CallType == "R")
            {
                lead.State = line.Substring(217, 2).Trim();
            }
            else if (lead.CallType == "B")
            {
                lead.State = line.Substring(148, 2).Trim();
            }
            else
            {
                if (lead.LeadType == "N")
                {

                    lead.State = line.Substring(217, 2).Trim();
                }
                else if (lead.LeadType == "B")
                {

                    lead.State = line.Substring(148, 2).Trim();
                }
                else
                {
                    // Noting to do.
                }
            }

            lead.RawData = line;
            //lead.ProsLeadCount = GetProsLeadCount(lead);

            return lead;
        }

        private Lead ConstructLeadForNB(string line)
        {
            Lead lead = new Lead();

            lead.SequenceNumber = line.Substring(0, 9).Trim();
            lead.SelPersonId = line.Substring(9, 9).Trim();
            lead.LeadBlockCode = line.Substring(18, 9).Trim();
            lead.Zip = line.Substring(18, 9).Substring(0, 5).Trim();
            lead.County = line.Substring(27, 27).Trim();
            lead.PreferCity = line.Substring(54, 27).Trim();
            lead.LeadType = line.Substring(81, 1).Trim();
            lead.Division = line.Substring(86, 2).Trim();
            lead.Market = line.Substring(88, 2).Trim();
            //lead.Territory = line.Substring(90, 2).Trim();
            lead.City = line.Substring(186, 27).Trim();

            lead.RawData = line;
            //lead.MdNumber = line.Substring(2723, 4).Trim();
            //lead.CallType = line.Substring(2790, 1).Trim();
            //lead.Latitude = line.Substring(2792, 9).Trim();
            //lead.Longitude = line.Substring(2801, 9).Trim();
            //lead.PersonStatus = line.Substring(2833, 1).Trim();
            //lead.PcLeadType = line.Substring(3009, 1).Trim();
            //lead.City = line.Substring(3070, 27).Trim();

            //if (lead.CallType == "R")
            //{
            //    lead.State = line.Substring(217, 2).Trim();
            //}
            //else if (lead.CallType == "B")
            //{
            //    lead.State = line.Substring(148, 2).Trim();
            //}
            //else
            //{
            //    if (lead.LeadType == "N")
            //    {

            //        lead.State = line.Substring(217, 2).Trim();
            //    }
            //    else if (lead.LeadType == "B")
            //    {

            //        lead.State = line.Substring(148, 2).Trim();
            //    }
            //    else
            //    {
            //        // Noting to do.
            //    }
            //}

            //lead.ProsLeadCount = GetProsLeadCount(lead);

            return lead;
        }

        private Lead ConstructLead(string line)
        {
            Lead lead = new Lead();

            lead.SelPersonId = line.Substring(0, 9).Trim();
            lead.CallType = line.Substring(2790, 1).Trim();
            lead.County = line.Substring(2736, 27).Trim();
            lead.City = line.Substring(2763, 27).Trim();
            lead.LeadBlockCode = line.Substring(2810, 9).Trim();
            lead.Division = line.Substring(2819, 2).Trim();
            lead.Market = line.Substring(2821, 2).Trim();
            //lead.Territory = line.Substring(2823, 2).Trim();
            lead.LeadType = line.Substring(2791, 1).Trim();
            lead.MdNumber = line.Substring(2723, 4).Trim();
            lead.SequenceNumber = line.Substring(2727, 9).Trim();




            lead.Latitude = line.Substring(2792, 9).Trim();
            lead.Longitude = line.Substring(2801, 9).Trim();




            lead.Zip = line.Substring(2810, 9).Substring(0, 5).Trim();
            lead.PcLeadType = line.Substring(2872, 1).Trim();
            lead.PersonStatus = line.Substring(2829, 1).Trim();
            lead.PreferCity = line.Substring(2763, 27).Trim();


            if (lead.CallType == "R")
            {
                lead.State = line.Substring(217, 2).Trim();
            }
            else if (lead.CallType == "B")
            {
                lead.State = line.Substring(148, 2).Trim();
            }
            else
            {
                if (lead.LeadType == "N")
                {

                    lead.State = line.Substring(217, 2).Trim();
                }
                else if (lead.LeadType == "B")
                {

                    lead.State = line.Substring(148, 2).Trim();
                }
                else
                {
                    // Noting to do.
                }
            }

            lead.RawData = line;
            lead.ProsLeadCount = GetProsLeadCount(lead);

            return lead;
        }

        private int GetProsLeadCount(Lead lead)
        {
            int count = 0;

            for (int i = 0; i < 4; i++)
            {
                if (!string.IsNullOrEmpty(lead.RawData.Substring(3109 + i * 197, 10).Trim()))
                {
                    count++;
                }
            }

            return count;
        }
    }
}
